package cn.szsys.integration.repository;

import cn.szsys.integration.billrule.entity.BillingRuleData;
import cn.szsys.integration.dos.BillingDayRecordDO;
import cn.szsys.integration.mapper.BillingDayRecordMapper;
import cn.szsys.integration.util.SnowIdUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.repository.CrudRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author Ryan
 * @description 针对表【billing_day_record】的数据库操作Service实现
 * @createDate 2025-05-09 15:07:48
 */
@Repository
@Slf4j
public class BillingDayRecordRepository extends CrudRepository<BillingDayRecordMapper, BillingDayRecordDO> {

    /**
     * 批处理,如果有当天的记录(上游+下游+日期)，则加上之前的值
     *
     * @param dataList dataList
     * @author Ryan
     */
    public void batchHandler(List<BillingRuleData> dataList) {
        Map<String, List<BillingRuleData>> groupMap = dataList.stream()
                .collect(Collectors.groupingBy(d -> d.getTheDay() + ";" + d.getUpAbbreviation() + ";" + d.getDownAbbreviation() + ";"+ d.getProduct()));
        for (String key : groupMap.keySet()) {
            List<BillingRuleData> ruleData = groupMap.get(key);
            String[] split = key.split(";");
            LambdaQueryWrapper<BillingDayRecordDO> wrapper = Wrappers.lambdaQuery();
            wrapper.eq(BillingDayRecordDO::getTheDay, split[0])
                    .eq(BillingDayRecordDO::getUpAbbreviation, split[1])
                    .eq(BillingDayRecordDO::getDownAbbreviation, split[2])
                    .eq(BillingDayRecordDO::getProduct, split[3]);
            long count = this.count(wrapper);
            BillingDayRecordDO billingDayRecordDO = aggregationData(ruleData, split[0], split[1], split[2]);
            //存在同日的数据(更新)
            if (count > 0) {
                try {
                    this.baseMapper.updateByTheDayAndAbbreviation(billingDayRecordDO);
                } catch (Exception e) {
                    log.info("[更新]计费按日统计数据,保存失败,数据:[{}],异常信息:[{}],e", billingDayRecordDO, e.getMessage(), e);
                }
            } else {
                //插入
                try {
                    save(billingDayRecordDO);
                } catch (DuplicateKeyException e) {
                    this.baseMapper.updateByTheDayAndAbbreviation(billingDayRecordDO);
                } catch (Exception e) {
                    log.info("[插入]计费按日统计数据,保存失败,数据:[{}],异常信息:[{}],e", billingDayRecordDO, e.getMessage(), e);
                }
            }
        }
    }

    /**
     * 将数据聚合成一条实体
     *
     * @param dataList dataList
     * @return {@link BillingDayRecordDO}
     * @author Ryan
     */
    private BillingDayRecordDO aggregationData(List<BillingRuleData> dataList, String theDay, String upAbbreviation, String downAbbreviation) {
        BillingDayRecordDO billingDayRecord = BillingDayRecordDO.builder()
                .id(SnowIdUtils.uniqueLong())
                .theDay(theDay)
                .product(dataList.get(0).getProduct())
                .upAbbreviation(upAbbreviation)
                .downAbbreviation(downAbbreviation)
                .build();

        int upBilledNum = 0;
        int downBilledNum = 0;
        int requestUpstreamNum = 0;
        int requestDownstreamNum = 0;
        for (BillingRuleData data : dataList) {
            if (data.getUpBilled()) {
                upBilledNum++;
            }
            if (data.getDownBilled()) {
                downBilledNum++;
            }
            if (data.getRequestUpstream()) {
                requestUpstreamNum++;
            }
            if (data.getRequestDownstream()) {
                requestDownstreamNum++;
            }
        }
        return billingDayRecord.setDownRecordBilling(downBilledNum)
                .setUpRecordBilling(upBilledNum)
                .setUpRequest(requestUpstreamNum)
                .setDownRequest(requestDownstreamNum);
    }

}




